package com.bancomer.main;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import com.bancomer.batch.BatchController;
import com.bancomer.batch.Constants;
import com.bancomer.batch.MapConstants;
import com.bancomer.batch.impl.BatchContext;
import com.bancomer.batch.pojo.Alert;
import com.bancomer.batch.pojo.AlertsContainer;
import com.bancomer.batch.pojo.FileHelper;
import com.bancomer.batch.pojo.PigScript;
import com.bancomer.batch.util.FilesWriter;
import com.bancomer.batch.util.StringConverter;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;


public class MainBatchController {

	public static void main(String[] args) throws Exception {
		PropertyConfigurator.configure("/home/cloudera/workspace/alerta06/core-batch-mvn/log4j.properties");
		Logger logger = Logger.getLogger("MainBatchController");
		XStream xstream = new XStream(new StaxDriver());
		String pathFileXML;
		Integer idAlert;
		AlertsContainer alertsContainer;
		Alert alert;
		
		if(args.length>=1){
			pathFileXML=(!"".equals(args[0]))?args[0]:"/home/cloudera/Documents/ALERTAS/ALERTAS.xml";
		}
		else{
			pathFileXML = "/home/cloudera/Documents/ALERTAS/ALERTAS.xml";
		}
	
		//to do reflection
		String impl="com.bancomer.batch.impl.BatchCotrollerImpl";
		
		xstream.alias("AlertsContainer", AlertsContainer.class);
		xstream.alias("Alert", Alert.class);
		xstream.alias("FileHelper", FileHelper.class);
		xstream.alias("PigScript", PigScript.class);
		alertsContainer= (AlertsContainer) xstream.fromXML(new File(pathFileXML));
		
		if(args.length>=2){
			try{
				idAlert = (!"".equals(args[1]))?Integer.valueOf(args[1]):-1;
			}
			catch(NumberFormatException e){
				throw new Exception("ID de alerta incorrecto");
			}
		}
		else{
			throw new Exception("ID de alerta incorrecto");
		}
		Alert newAlert = new Alert();
		newAlert.setIdAlert(idAlert);
		int alertIndex = alertsContainer.getAlerts().indexOf(newAlert);
		
		if(alertIndex == -1){
			throw new Exception("Alerta con id "+idAlert.intValue()+" no encontrada en el archivo de configuración");
		}
		alert=alertsContainer.getAlerts().get(alertIndex);
		
		MapConstants mapConstants = MapConstants.getInstance(alert.getProperties().getProperty("constantsFile"));
		final Properties alertConstants = mapConstants.getConstants();
		
		if(alert.getAlertDate()!=null && !"".equals(alert.getAlertDate())){
			Constants.alertDate= alert.getAlertDate();
		}
		if(alert.getPatternAlertDate()!=null && !"".equals(alert.getPatternAlertDate())){
			Constants.formatDate= alert.getPatternAlertDate();
		}
		if(args.length>=3){
			if(!"".equals(args[2])){
				Constants.alertDate = args[2];
			}
		}
		if(args.length==4){
			if(!"".equals(args[3])){
				Constants.formatDate = args[3];
			}
		}
		if(Constants.alertDate==null || "".equals(Constants.alertDate)){
			Constants.alertDate=StringConverter.convertPatternToDate("yyMMdd"); 
		}
		
		@SuppressWarnings("unchecked")
		Class<BatchController> userClass = (Class<BatchController>) Class.forName(impl);      
		
		BatchController controller= (BatchController) userClass.newInstance();
		
		BatchContext batchContext= new BatchContext();
		
		batchContext.setContextParam(new HashMap<String,Object>());			
		
		controller.setBatchContext(batchContext);
		
		try{
			batchContext.getContextParam().put("xmlFilePath", pathFileXML);
			batchContext.getContextParam().put("alert", alert);
			
			controller.init();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("init: SUCCES ");
			
			controller.validateFiles();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("validateFiles: SUCCES ");
			
			controller.putFilesToHdfs();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("putFilesToHdfs: SUCCES ");
			
			controller.executePig();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("executePig: SUCCES ");
			
			controller.getFilesOnHdfs();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("getFilesOnHdfs: SUCCES ");
			
			controller.prepareResponseFiles();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("prepareResponseFiles: SUCCES ");
			
			controller.sendResponseFiles();
			if(batchContext.getContinueFlow()==false)
				throw new Exception(batchContext.getMsgError());
			logger.info("sendResponseFiles: SUCCES ");
			batchContext.getContextParam().put("alertEnding", new Date().getTime());
			long alertBeginning = (long)batchContext.getContextParam().get("alertBeginning");
			long alertEnding = (long)batchContext.getContextParam().get("alertEnding");
			long alertDuration = alertEnding - alertBeginning;
			SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
	        
			long days = TimeUnit.MILLISECONDS.toDays(alertDuration);
	        alertDuration -= TimeUnit.DAYS.toMillis(days);
	        long hours = TimeUnit.MILLISECONDS.toHours(alertDuration);
	        alertDuration -= TimeUnit.HOURS.toMillis(hours);
	        long minutes = TimeUnit.MILLISECONDS.toMinutes(alertDuration);
	        alertDuration -= TimeUnit.MINUTES.toMillis(minutes);
	        long seconds = TimeUnit.MILLISECONDS.toSeconds(alertDuration);
	        alertDuration -= TimeUnit.SECONDS.toMillis(seconds);
	        long milliseconds = TimeUnit.MILLISECONDS.toMillis(alertDuration);
	        
	        StringBuilder duration = new StringBuilder();
	        duration.append(days);
	        duration.append(" Days, ");
	        duration.append(hours);
	        duration.append(" Hours, ");
	        duration.append(minutes);
	        duration.append(" Minutes, ");
	        duration.append(seconds);
	        duration.append(" Seconds, ");
	        duration.append(milliseconds);
	        duration.append(" Milliseconds");
	       
	        String beginningDate = dateFormat.format(new Date(alertBeginning));
	        String endingDate = dateFormat.format(new Date(alertEnding));
	        logger.info("Date of execution: "+Constants.alertDate);
	        logger.info("Alert beginnning: "+beginningDate+"  Alert ending: "+endingDate);
	        logger.info("Alert duration: "+duration.toString());
		
		}catch(Exception e){
			logger.error("Error: "+e.getMessage());
			for(int i = 0; i<e.getStackTrace().length;i++){
				logger.error(e.getStackTrace()[i]);
			}
			FileHelper summaryFile = null;
			FileHelper detailFile = null;
			for(FileHelper fileHelper : alert.getOutputFiles()){
				if(fileHelper.getType().equals(alertConstants.getProperty("FILE_OUTPUT"))){
					if(fileHelper.getProperties().getProperty("outputType").equals(alertConstants.getProperty("OUTPUT_TYPE_SUMMARY"))){
						summaryFile = fileHelper;
					}
					if(fileHelper.getProperties().getProperty("outputType").equals(alertConstants.getProperty("OUTPUT_TYPE_DETAIL"))){
						detailFile = fileHelper;
					}
				}
			}
			summaryFile.setName(StringConverter.convertPatternToDate(summaryFile.getName()));
			FilesWriter.writeFile("", summaryFile.getLocalPath()+summaryFile.getName(), false);
			detailFile.setName(StringConverter.convertPatternToDate(detailFile.getName()));
			FilesWriter.writeFile("", detailFile.getLocalPath()+detailFile.getName(), false);
			throw e;
		}
	}

}
